package com.example.demo.controller;

import com.example.demo.service.OllamaService;
import com.example.demo.utils.Result;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.ollama.api.OllamaOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@RestController
@RequestMapping("/api/ollama")
@RequiredArgsConstructor
public class OllamaController<Chat> {
    @Autowired
    private  OllamaService ollamaService;

    @PostMapping("/generate")
    public Mono<String> generateText(
            @RequestParam(defaultValue = "deepseek-r1:1.5b") String model,
            @RequestParam String prompt,
            @RequestParam(required = false) Double temperature) {
        return ollamaService.generateText(model, prompt, temperature);
    }

    @PostMapping("/chat")
    public Mono<String> chat(
            @RequestParam(defaultValue = "deepseek-r1:1.5b") String model,
            @RequestBody List<Map<String, String>> messages) {
        return ollamaService.chat(model, messages);
    }

    @PostMapping("/stream")
    public Flux<String> streamGenerateText(
            @RequestParam(defaultValue = "deepseek-r1:1.5b") String model,
            @RequestParam String prompt,
            @RequestParam(required = false) Double temperature) {
        return ollamaService.streamGenerateText(model, prompt, temperature);
    }
    /**
     * 回答写入.md文件
     * 此方法接收用户消息，调用聊天模型生成回复，并将回复内容写入markdown文件中
     * 主要用于演示如何将聊天内容转换为文档保存
     *
     * @param msg 用户输入的消息，用于生成聊天回复
     * @return 聊天模型生成的回复内容
     */
    @Operation(summary = "回答写入.md文件")
    @GetMapping("/chatToMd")
    public String chatToMd(@RequestParam String msg) {
        // 调用Ollama API获取回复
        Mono<String> responseMono = ollamaService.chat("deepseek-r1:1.5b", List.of(
                Map.of("role", "user", "content", msg)
        ));

        // 订阅响应并处理结果
        responseMono.subscribe(
                response -> {
                    try {
                        // 构建Markdown内容
                        String markdownContent = "# user\n" +
                                msg + "\n\n" +
                                "# AI\n" +
                                response+"\n\n";

                        // 生成唯一文件名（使用时间戳）
                        String fileName = "chat_file.md";
//                        String fileName = "chat_" + System.currentTimeMillis() + ".md";
                        Path filePath = Path.of("src/main/resources/static", fileName);

                        // 检查文件是否存在，不存在则创建
                        if (!Files.exists(filePath)) {
                            Files.createDirectories(filePath.getParent());
                            Files.createFile(filePath);
                        }

                        // 追加写入文件
                        Files.writeString(filePath, markdownContent, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
                        // 写入文件
//                        Files.writeString(filePath, markdownContent, StandardCharsets.UTF_8);

                        System.out.println("Markdown文件已生成: " + filePath);
                    } catch (IOException e) {
                        throw new RuntimeException("写入Markdown文件失败", e);
                    }
                },
                error -> {
                    System.err.println("调用Ollama API失败: " + error.getMessage());
                    throw new RuntimeException("获取AI回复失败", error);
                }
        );

        return "正在生成Markdown文件，请稍后查看";
    }
    /**
     * 读取Markdown文件内容
     */
    @GetMapping("/readerFile")
    public String readerFile() {
        Path filePath = Path.of("src/main/resources/static/chat_file.md");
        StringBuilder keywords = new StringBuilder();

        try {
            String content = Files.readString(filePath, StandardCharsets.UTF_8);

            // 使用正则表达式提取用户提问内容
            Pattern pattern = Pattern.compile("# user\n(.*?)\n\n# AI", Pattern.DOTALL);
            Matcher matcher = pattern.matcher(content);

            // 提取所有用户提问的关键词
            while (matcher.find()) {
                String userQuestion = matcher.group(1).trim();
                // 简单提取关键词（实际应用中可使用更复杂的NLP算法）
                String[] words = userQuestion.split("\\s+");
                for (String word : words) {
                    if (word.length() > 2) { // 过滤短词
                        keywords.append(word).append(", ");
                    }
                }
            }

            // 去除最后一个逗号
            if (keywords.length() > 0) {
                keywords.setLength(keywords.length() - 2);
            }

        } catch (IOException e) {
            throw new RuntimeException("读取Markdown文件失败", e);
        }

        return keywords.toString();

    }
    // 简易的Map转JSON方法（实际项目建议使用Jackson/Gson等库）
    private static String mapToJson(Map<String, Object> map) {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        boolean first = true;

        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (!first) {
                sb.append(",");
            }
            sb.append("\"").append(entry.getKey()).append("\":");

            Object value = entry.getValue();
            if (value instanceof String) {
                sb.append("\"").append(escapeJson((String) value)).append("\"");
            } else {
                sb.append(value.toString());
            }
            first = false;
        }

        sb.append("}");
        return sb.toString();
    }

    // 转义JSON中的特殊字符
    private static String escapeJson(String input) {
        return input.replace("\\", "\\\\")
                .replace("\"", "\\\"")
                .replace("\n", "\\n")
                .replace("\r", "\\r")
                .replace("\t", "\\t");
    }
}
